﻿using System;
using System.Collections.Generic;

namespace VietNamKey
{
	public class VNWord
	{
		/// <summary>
		/// Nguyên âm
		/// </summary>
		public string Vowel { get; set; }
		public string sVowel(int Index) { return Vowel[Index].ToString(); }
		/// <summary>
		/// Phụ âm đầu
		/// </summary>
		public string InitialConsonant { get; set; }
		/// <summary>
		/// Phụ âm cuối
		/// </summary>
		public string FinalConsonant { get; set; }
		/// <summary>
		/// Dấu
		/// </summary>
		public char Accent { get; set; }
		/// <summary>
		/// Ký tự dấu chưa thay đổi hoa thường
		/// </summary>
		public char LastChar { get; set; }
		private ItemTypingMethod TypingMethod { get{ return TypingMethods.List[Global.KeySettings.TypingMethod]; } }
		/// <summary>
		/// Vị trí bỏ Dấu trong nguyên âm
		/// </summary>
		public int TypingMethodIndex 
		{
			get
			{
				if(Vowel.Length < 1 || Accent == TypingMethod.DD) return -1;
				string UnSign = Encodings.ConvertToUnsign(Vowel).ToLower();
				if(UnSign.Length > 2)
					if("uou,ieu,uyu,yeu,oai,uoi,uay,oay,uya,oeo".Contains(UnSign)) return 1;
					else if(UnSign == "uye") return 2;
						else return -1;
				else if(UnSign.Length > 1)
					if("ai,ao,au,ay,oi,eo,eu,uu,ui,iu,ia".Contains(UnSign)) return 0;
					else
					{
						if("uy,oa,oe".Contains(UnSign)) 
							return Global.KeySettings.UseNewStyle ? 1 : (FinalConsonant.Length > 0 ? 1 : 0);
						string UnSign2 = VNStatic.RemoveSign(Vowel).ToLower();
						if("ua,ưa".Contains(UnSign2) && (Accent == TypingMethod.Acute || Accent == TypingMethod.Grave || Accent == TypingMethod.Hook || Accent == TypingMethod.Tilde || Accent == TypingMethod.Heavy || Accent == TypingMethod.RemoveAccent || Accent == TypingMethod.UW))
							return 0;
						return 1;
					} 
				else return 0;
			}
		}
		/// <summary>
		/// Lỗi khởi tạo
		/// </summary>
		public bool Error { get; set; }
		
		public string Value	{ get { return InitialConsonant + Vowel + FinalConsonant; } }
		
		public void Reset()
		{
        	Vowel = InitialConsonant = FinalConsonant = "";
        	Accent = LastChar = '\b';
		}
		
		public void RemoveChar()
		{
			if(FinalConsonant.Length > 0)
			{
				FinalConsonant = FinalConsonant.Substring(0, FinalConsonant.Length - 1);
				if(Error && FinalConsonant.ToLower().IndexOfAny(new[]{'a', 'e', 'i', 'y', 'o', 'u'}) < 0) 
					Error = false;
				if(FinalConsonant.Length == 0) 
				{
					if(!Global.KeySettings.UseNewStyle) // không cần kt độ dài Vowel vì có phụ âm cuối => đã có nguyên âm 
					{ // trường hợp bỏ dấu kiểu cũ hoàn -> hòa thay lại vị trí dấu nguyên âm
						int sign = 0;
						string tmp = VNStatic.RemoveSign(Vowel, out sign);
						if(sign > 0)
						{
							Vowel = tmp;
							int TMI = TypingMethodIndex;
							if(TMI > -1)
							{
								int index = VNStatic.UNI.IndexOf(sVowel(TMI));
								ChangeChar(TMI, VNStatic.UNI[index + sign][0]);
							}
						}
					}
				}
			}
			else if(Vowel.Length > 0)
			{
				Vowel = Vowel.Substring(0, Vowel.Length - 1);
			}
			else if(InitialConsonant.Length > 0)
			{
				InitialConsonant = InitialConsonant.Substring(0, InitialConsonant.Length - 1);
			}
			else return;
			string IC = InitialConsonant.ToLower();
			if(Vowel.Length == 0 && (IC == "qu" || IC == "gi"))
			{
				Vowel = InitialConsonant.Substring(1, 1);
				InitialConsonant = InitialConsonant.Substring(0, 1);
			}
//			System.Diagnostics.Debug.Print("Remove = '{0}'", Value);
		}
		
		public void AddChar(char value)
		{
			// kiểm tra xem có phải là dấu để bỏ ko, nếu là dấu thì bỏ, không thì add vào cuối
			if(!Error && TypingMethod.Contains(value))
			{
				LastChar = value;
				Accent = TypingMethod.Get(value);
				if(ToVN()) 
					return;
			}
			LastChar = Accent = '\b';
			Add(value);
		}
		
		private void AddRange(string sText)
		{
			for(int i = 0; i < sText.Length; i++)
				AddChar(sText[i]);
		}
		
		private void Add(char value)
		{ 
//			System.Diagnostics.Debug.Print("Before ADD = '{0}'", Value);
			if("aeiyou".Contains(Encodings.ConvertToUnsign(char.ToLower(value).ToString())))
			{
				if(FinalConsonant.Length == 0)
				{
					bool isChanged = false;
					if(InitialConsonant.Length == 1 && "qQ".Contains(InitialConsonant) && char.ToLower(value) == 'u')
					{
						InitialConsonant += value;
						isChanged = true;
					}
					else 
					{
						if(InitialConsonant.Length == 1 && "gG".Contains(InitialConsonant) && Vowel.Length == 1 && char.ToLower(Vowel[0]) == 'i')
						{
							InitialConsonant += Vowel[0];
							Vowel = "";
						}
						else if(Vowel.Length > 0)
						{
//							// sửa lại vị trí dấu cho phù hợp khi nguyên âm thay đổi
							int sign = 0;
							string tmp = VNStatic.RemoveSign(Vowel, out sign);
							if(sign > 0)
							{
								Vowel = tmp + value;
								int TMI = TypingMethodIndex;
								if(TMI != -1)
								{
									int index = VNStatic.UNI.IndexOf(sVowel(TMI));
									ChangeChar(TMI, VNStatic.UNI[index + sign][0]);
									isChanged = true;
								}
							}
						}
					}
					if(!isChanged) Vowel += value;
					ShorhandIC();
				}
				else
				{			
					Error = true;
					FinalConsonant += value;
				}
			}
			else if(Vowel.Length == 0)
			{
				InitialConsonant += value;
			}
			else
			{
				FinalConsonant += value;
				if(FinalConsonant.Length == 1 && !Global.KeySettings.UseNewStyle) // không cần kt độ dài Vowel vì có phụ âm cuối => đã có nguyên âm 
				{ // trường hợp bỏ dấu kiểu cũ hòa -> hoàn thay lại vị trí dấu nguyên âm
					int sign = 0;
					string tmp = VNStatic.RemoveSign(Vowel, out sign);
					if(sign > 0)
					{
						Vowel = tmp;
						int TMI = TypingMethodIndex;
						int index = VNStatic.UNI.IndexOf(sVowel(TMI));
						ChangeChar(TMI, VNStatic.UNI[index + sign][0]);
					}
				}
			}
//			System.Diagnostics.Debug.Print("After ADD = '{0}'", Value);
		}
		
		private void GiQu()
		{
			string IC = InitialConsonant.ToLower();
			if((IC == "q" && Vowel.Length > 1 && char.ToLower(Vowel[0]) == 'u')
			   ||(IC == "g" && Vowel.Length > 1 && char.ToLower(Vowel[0]) == 'i'))
			{
				InitialConsonant += Vowel[0];
				Vowel = Vowel.Substring(1);
			}
		}
		
		public VNWord()
		{
			Error = false;
			Vowel = InitialConsonant = FinalConsonant = "";
		}
		public VNWord(String sText) : this()
		{ 
			Accent = TypingMethod.Get(sText[sText.Length - 1]);
			LastChar = sText[sText.Length - 1];
			AddRange(sText.Substring(0, sText.Length - 1));
		}	
		
		private void ShorhandIC()
		{
			if(Global.KeySettings.AutoIC && Vowel.Length > 0)
			{
				string IC = InitialConsonant.ToLower(); // khai lại vì phía trên có thể InitialConsonant bị đổi
				bool IsICLower = InitialConsonant == IC;
				bool IsHavelUpper = Vowel != Vowel.ToLower();
				if(IC == "f" && Global.KeySettings.IC_F2PH) InitialConsonant = IsICLower ? "ph" : (IsHavelUpper ? "PH" : "Ph");
				if(IC == "k" && Global.KeySettings.IC_K2KH_C2K) InitialConsonant = IsICLower ? "kh" : (IsHavelUpper ? "KH" : "Kh");
				if(IC == "z" && Global.KeySettings.IC_D2DD_Z2D) InitialConsonant = IsICLower ? "d" : "D";
				if(IC == "d" && Global.KeySettings.IC_D2DD_Z2D) InitialConsonant = IsICLower ? "đ" : "Đ";
				if(IC == "j" && Global.KeySettings.IC_J2GI) InitialConsonant = IsICLower ? "gi" : (IsHavelUpper ? "GI" : "Gi");
				if(IC == "q" && Global.KeySettings.IC_Q2QU) InitialConsonant = IsICLower ? "qu" : (IsHavelUpper ? "QU" : "Qu");
				
				if(Vowel.Length > 0)
				{
					string VUS = VNStatic.RemoveSign(sVowel(0));
					if(IC == "c" && Global.KeySettings.IC_K2KH_C2K && "yieê".Contains(VUS)) InitialConsonant = IsICLower ? "k" : "K";
					if(IC == "ng" && Global.KeySettings.IC_NG2NGH && "ieê".Contains(VUS)) InitialConsonant = IsICLower ? "ngh" : (IsHavelUpper ? "NGH" : "Ngh");
					if(IC == "g" && Global.KeySettings.IC_G2GH && "ieê".Contains(VUS) && VNStatic.RemoveSign(Vowel).ToLower() != "i") InitialConsonant = IsICLower ? "gh" : (IsHavelUpper ? "GH" : "Gh");
				}
			}
		}
		
		public void ShorthandFC()
		{
			string FC = FinalConsonant.ToLower();
			if(Global.KeySettings.AutoFC)
			{
				bool IsFCLower = FinalConsonant == FC;
				bool IsHavelUpper = Vowel != Vowel.ToLower() || !IsFCLower;
				if(FC == "g" && Global.KeySettings.FC_G2NG) FinalConsonant = IsFCLower ? "ng" : "NG";
				if(FC == "h" && Global.KeySettings.FC_H2NH) FinalConsonant = IsFCLower ? "nh" : "NH";
				if(FC == "k" && Global.KeySettings.FC_K2CH) FinalConsonant = IsFCLower ? "ch" : "CH";
			}
			if(Global.KeySettings.AutoAcute && VNStatic.SacNang.Contains(FC))
			{ 
				int TMI = TypingMethodIndex;
				int Index = VNStatic.UNI.IndexOf(sVowel(TMI));
				int SignIndex = VNStatic.GetSignIndex(Index);
				if(SignIndex == 0)
					ChangeChar(TMI, VNStatic.UNI[Index + TypingMethod.IndexOf(TypingMethod.Acute)][0]);
			}
		}
		
		public bool CheckInitialConsonant()
		{
			string IC = InitialConsonant.ToLower();
			if(IC.Length < 1) return true;
			if(VNStatic.PhuAm.Contains(IC))
				return true;
			else if( Global.KeySettings.AutoIC && ((Global.KeySettings.IC_D2DD_Z2D && IC == "z")
			                                       ||(Global.KeySettings.IC_F2PH && IC == "f")
			                                     //||(Global.KeySettings.IC_G2GH && IC == "g")
			                                       ||(Global.KeySettings.IC_J2GI && IC == "j")
			                                     //||(Global.KeySettings.IC_K2KH_C2K && IC == "k")
			                                     //||(Global.KeySettings.IC_NG2NGH && IC == "ng")
			                                       ||(Global.KeySettings.IC_Q2QU && IC == "q")
                  )) return true;
			else return false;
		}
		public bool CheckFinalConsonant()
		{
			string FC = FinalConsonant.ToLower();
			if(FC.Length < 1) return true;
			if(VNStatic.PhuAmCuoi.Contains(FC))
				if(VNStatic.SacNang.Contains(FC))
					return Accent != TypingMethod.Hook && Accent != TypingMethod.Tilde && Accent != TypingMethod.Grave;
				else return true;
			else if (Global.KeySettings.AutoFC && ((Global.KeySettings.FC_G2NG && FC == "g")
													||(Global.KeySettings.FC_H2NH && FC == "h")
													||(Global.KeySettings.FC_K2CH && FC == "k")))
					return true;
			else return false;
		}
		public void ChangeChar(int Index, char NewChar)
		{
			string pre = Index > 0 ? Vowel.Substring(0, Index) : "";
			string next = Vowel.Length > Index + 1 ? Vowel.Substring(Index + 1): "";
			Vowel = pre + NewChar + next;
		}
		public bool isVNWord()
		{
			if(Vowel.Length == 0) return true;
			string sUnsign = Encodings.ConvertToUnsign(InitialConsonant + Vowel + FinalConsonant);
			if(sUnsign == (InitialConsonant + Vowel + FinalConsonant)) return true;
			//Phụ âm đầu không có
			if(Global.KeySettings.CheckSpellingLevel > 0 && InitialConsonant.Length > 0 && VNStatic.PhuAm.IndexOf(InitialConsonant.ToLower()) < 0) return false;
			int sign = 0;
			string sUnSign2 = VNStatic.RemoveSign(Vowel, out sign).ToLower();
			string IC = InitialConsonant.ToLower();
			string FC = FinalConsonant.ToLower();
			if(VNStatic.NguyenAm.IndexOf(sUnSign2) < 0) return false;
			if(Vowel.Length > 0 && InitialConsonant.Length > 0 && Global.KeySettings.CheckSpellingLevel > 1)
			{
				string cNA = sUnSign2.Substring(0, 1);
				if(((new List<string>(){"g","ng"}).Contains(IC) && "yieê".Contains(cNA) && sUnsign.ToLower() != "gi")
					||((new List<string>(){"gh","ngh"}).Contains(IC) && "ieê".IndexOf(cNA) < 0)
					||(IC == "c" && ((new List<string>(){"oa","oă","oe","uy","uơ","uô","uê","uâ","oai","oay","uây","uyê","uya","oeo","oao"}).Contains(sUnSign2) || "yieê".Contains(cNA)))
					||(IC == "k" && "yieê".IndexOf(cNA) < 0)
					||(IC == "qu" && "ou".Contains(cNA) && Vowel.Length > 1)
				)
					return false;
			}
			if(FinalConsonant.Length > 0)
			{
				if(!VNStatic.PhuAmCuoi.Contains(FC) && Global.KeySettings.CheckSpellingLevel > 0)
					return false;
				if(Global.KeySettings.CheckSpellingLevel > 1 && VNStatic.SacNang.Contains(FC) && sign != TypingMethod.IndexOf(TypingMethod.Acute) && sign != TypingMethod.IndexOf(TypingMethod.Heavy))
					return false;
				if(Global.KeySettings.CheckSpellingLevel > 1 && VNStatic.NguyenAmCuoi.Contains(sUnSign2)) return false;
			}
			else if(Global.KeySettings.CheckSpellingLevel > 1 && Vowel.Length > 0 && VNStatic.NguyenAmGiua.Contains(sUnSign2)) return false;
			return true;
		}
		
		private bool ToVN()
		{
			if(Global.KeySettings.UseCheckSpelling && Global.KeySettings.CheckSpellingLevel > 0 && !CheckInitialConsonant())
            	return false; //có phụ âm đầu không hợp lệ.
#region Hỗ trợ gõ tắt nguyên âm 
			if(Vowel.Length == 1 && FinalConsonant.Length == 0 && Global.KeySettings.VowelsShorthand > 0
   										&& (Accent == TypingMethod._S
										|| Accent == TypingMethod._J 
										|| Accent == TypingMethod._V 
										|| Accent == TypingMethod._L 
										|| Accent == TypingMethod._Z 
										|| Accent == TypingMethod._W 
										|| Accent == TypingMethod._F 
										|| Accent == TypingMethod._D))
			{
				int sign = 0; // tách dấu ra
				string str = VNStatic.RemoveSign(Value.ToLower(), out sign) + LastChar;
				string[] sV = Global.KeySettings.VowelsShorthand == 1 ? VNStatic.SVowelUnsign : VNStatic.SVowel;
				for(int i = 0; i < sV.Length; i += 2)
				{
					string st = str.Length > sV[i].Length ? str.Substring(str.Length - sV[i].Length) : str;
					string stV = st.Substring(0, st.Length - 1);
					char chV = st[st.Length - 1];
					if(chV == TypingMethod._S) stV += "s";
					else if(chV == TypingMethod._J) stV += "j";
					else if(chV == TypingMethod._V) stV += "v"; 
					else if(chV == TypingMethod._L) stV += "l"; 
					else if(chV == TypingMethod._Z) stV += "z"; 
					else if(chV == TypingMethod._W) stV += "w"; 
					else if(chV == TypingMethod._F) stV += "f"; 
					else if(chV == TypingMethod._D) stV += "d";
					else continue; //Không thấy
					if(sV[i] == stV) //Tìm thấy thì gắn dấu và xuất
					{
						string result = char.IsUpper(Vowel[0]) ? sV[i + 1].ToUpper() : sV[i + 1];
						InitialConsonant = Vowel = FinalConsonant = "";
						AddRange(str.Substring(0, str.Length - st.Length) + result);
						char ValueOfSign = TypingMethod.ValueOf(sign);
						if(ValueOfSign != '\b') AddChar(ValueOfSign);
						return true;
					}
				}
			}
#endregion
			if(Global.KeySettings.UseCheckSpelling && Global.KeySettings.CheckSpellingLevel > 0 && !CheckFinalConsonant())
            	return false; //có phụ âm cuối không hợp lệ.
#region Bắt đầu việc bỏ dấu cho nguyên âm
	#region Chữ D
            if(Accent == TypingMethod.DD && InitialConsonant.Length == 1 && "dD".Contains(InitialConsonant))
            {// bỏ dấu cho chữ D
            	InitialConsonant = VNStatic.UNI[VNStatic.UNI.IndexOf(InitialConsonant) + 1];
            	return true;
            }
	            
            if(Accent  == TypingMethod.DD && InitialConsonant.Length == 1 && "đĐ".Contains(InitialConsonant))
            {// Xoá dấu cho chữ Đ
            	InitialConsonant = VNStatic.UNI[VNStatic.UNI.IndexOf(InitialConsonant) - 1];
            	FinalConsonant += LastChar;
            	return true;
            }
	#endregion
            int TMI = TypingMethodIndex; // Lấy vị trí bỏ dấu
	#region Các chữ cái đơn
			if(FinalConsonant.Length == 0)
			{
	            if(Accent == TypingMethod.CUW && (TMI < 0 || TypingMethod != TypingMethods.Telex))
	            {
	            	if(Vowel.Length > 0 && "ưƯ".Contains(sVowel(Vowel.Length - 1))) 
	            		ChangeChar(Vowel.Length - 1, LastChar);
	            	else
	            		Vowel += LastChar == Accent ? "ư" : "Ư";
	            	return true;
	            }
	            if(Accent == TypingMethod.CAA)
	            {
	            	if(Vowel.Length > 0 && "âÂ".Contains(sVowel(Vowel.Length - 1))) 
	            		ChangeChar(Vowel.Length - 1, LastChar);
	            	else
	            		Vowel += LastChar == Accent ? "â" : "Â";
	            	return true;
	            }
	            if(Accent == TypingMethod.CAW)
	            {
	            	if(Vowel.Length > 0 && "ăĂ".Contains(sVowel(Vowel.Length - 1))) 
	            		ChangeChar(Vowel.Length - 1, LastChar);
	            	else
	            		Vowel += LastChar == Accent ? "ă" : "Ă";
	            	return true;
	            }
	            if(Accent == TypingMethod.COO)
	            {
	            	if(Vowel.Length > 0 && "ôÔ".Contains(sVowel(Vowel.Length - 1))) 
	            		ChangeChar(Vowel.Length - 1, LastChar);
	            	else
	            		Vowel += LastChar == Accent ? "ô" : "Ô";
	            	return true;
	            }
	            if(Accent == TypingMethod.COW)
	            {
	            	if(Vowel.Length > 0 && "ơƠ".Contains(sVowel(Vowel.Length - 1))) 
	            		ChangeChar(Vowel.Length - 1, LastChar);
	            	else
	            		Vowel += LastChar == Accent ? "ơ" : "Ơ";
	            	return true;
	            }
	            if(Accent == TypingMethod.CEE)
	            {
	            	if(Vowel.Length > 0 && "êÊ".Contains(sVowel(Vowel.Length - 1))) 
	            		ChangeChar(Vowel.Length - 1, LastChar);
	            	else
	            		Vowel += LastChar == Accent ? "ê" : "Ê";
	            	return true;
	            }
	            if(Accent == TypingMethod.CDD && (Value.Length == 0 ||(Value.Length == 1 && "đĐ".Contains(InitialConsonant))))
	            {
	            	if(InitialConsonant.Length > 0 && "đĐ".Contains(sVowel(Vowel.Length - 1))) 
	            		InitialConsonant = LastChar.ToString();
	            	else
	            		InitialConsonant = LastChar == Accent ? "đ" : "Đ";
	            	return true;
	            }
	            if(Accent == TypingMethod.CD && Value.Length == 0)
	            {
	            	InitialConsonant = LastChar == Accent ? "d" : "d";
	            	return true;
	            }
			}
	#endregion
            if(TMI < 0) 
            	return false; // Không tìm thấy chỗ để bỏ dấu
            // Lấy vị trí chữ cái cần bỏ dấu trong danh sách UNICODE được lập sẵn
            int index = VNStatic.UNI.IndexOf(sVowel(TMI));
	#region Sắc huyền hỏi ngã nặng
           	if(Accent == TypingMethod.Acute
        		|| Accent == TypingMethod.Grave
        		|| Accent == TypingMethod.Tilde
        		|| Accent == TypingMethod.Hook
        		|| Accent == TypingMethod.Heavy
    			|| Accent == TypingMethod.RemoveAccent)
            {// Bỏ các dấu thanh và xử trường hợp xoá dấu thanh.GetSignIndex(index) để lấy dấu cũ, xoá nó đi để thêm dấu mới
            	string newChar = VNStatic.UNI[index - VNStatic.GetSignIndex(index) + TypingMethod.IndexOf(Accent)];
            	string removeChar = VNStatic.UNI[index - VNStatic.GetSignIndex(index)];
            	FinalConsonant += newChar == sVowel(TMI) ? LastChar.ToString(): "" ;
            	ChangeChar(TMI, newChar == sVowel(TMI) ? removeChar[0] : newChar[0]);
            	return true;
            }
	#endregion
	#region Mũ và móc
            if(Accent == TypingMethod.AA && VNStatic.a.Contains(sVowel(TMI)))
            {// Bỏ mũ cho chữ A -> Â (Bao gồm trường hợp xoá dấu)
            	int Si = SubtracIndex(Vowel[TMI]);
            	string newChar = VNStatic.UNI[index + 12 - Si];
            	string removeChar = VNStatic.UNI[index - Si];
            	FinalConsonant += newChar == sVowel(TMI) ? LastChar.ToString(): "" ;
            	bool changed = false;
            	if(TMI == 1 && VNStatic.u.Contains(sVowel(0)) && VNStatic.a.Contains(sVowel(1)))
				{ // Xét và xử lý trường hợp túa -> tuấ và tuấ -> huáa
            		int pindex = VNStatic.UNI.IndexOf(sVowel(0));
            		Vowel = VNStatic.UNI[pindex - SubtracIndex(Vowel[0]) - VNStatic.GetSignIndex(pindex)] + (newChar == sVowel(TMI) ? removeChar : VNStatic.UNI[VNStatic.UNI.IndexOf(newChar) + VNStatic.GetSignIndex(pindex)]) + (Vowel.Length > 2 ? Vowel.Substring(2) : "");
					changed = true;
				}
            	if(!changed) ChangeChar(TMI, newChar == sVowel(TMI) ? removeChar[0] : newChar[0]);
            	return true;
            }
                                    
            if((Accent == TypingMethod.AW && VNStatic.a.Contains(sVowel(TMI)))
	        	||(Accent == TypingMethod.EE && VNStatic.e.Contains(sVowel(TMI))))
            { // xử lý chung cho A -> Ă, E -> Ê
            	int Si = SubtracIndex(Vowel[TMI]);
            	string newChar = VNStatic.UNI[index + 6 - Si];
            	string removeChar = VNStatic.UNI[index - Si];
            	FinalConsonant += newChar == sVowel(TMI) ? LastChar.ToString(): "" ;
            	ChangeChar(TMI, newChar == sVowel(TMI) ? removeChar[0] : newChar[0]);
            	return true;
            }
            
            if(Accent == TypingMethod.OO && VNStatic.o.Contains(sVowel(TMI)))
            { // xử lý O -> Ô
            	int Si = SubtracIndex(Vowel[TMI]);
            	string newChar = VNStatic.UNI[index + 6 - Si];
            	string removeChar = VNStatic.UNI[index - Si];
            	FinalConsonant += newChar == sVowel(TMI) ? LastChar.ToString(): "" ;
            	bool changed = false;
            	if(TMI == 1 && VNStatic.u.Contains(sVowel(0)))
				{// Xét và xử lý trường hợp húo -> huố và huố -> huó
            		int pindex = VNStatic.UNI.IndexOf(sVowel(0));
            		Vowel = VNStatic.UNI[pindex - SubtracIndex(Vowel[0]) - VNStatic.GetSignIndex(pindex)] + (newChar == sVowel(TMI) ? removeChar : VNStatic.UNI[VNStatic.UNI.IndexOf(newChar) + VNStatic.GetSignIndex(pindex)]) + (Vowel.Length > 2 ? Vowel.Substring(2) : "");
					changed = true;
				}
            	if(!changed) ChangeChar(TMI, newChar == sVowel(TMI) ? removeChar[0] : newChar[0]);
            	return true;
            }
			
            if((Accent == TypingMethod.OW && VNStatic.o.Contains(sVowel(TMI)))
               || (Accent == TypingMethod.UW && VNStatic.u.Contains(sVowel(TMI))))
            {
            	int Si = SubtracIndex(Vowel[TMI]);
            	string newChar = VNStatic.UNI[index + (VNStatic.o.Contains(sVowel(TMI)) ? 12 : 6) - Si];
            	string removeChar = VNStatic.UNI[index - Si];
            	bool changed = false;
            	if(TMI == 1 && VNStatic.u.Contains(sVowel(0)) && VNStatic.o.Contains(sVowel(1)))
				{// uow => ươ !!! húo -> huớ -> hướ -> huów
					int pindex = VNStatic.UNI.IndexOf(sVowel(0));
					if(InitialConsonant.Length > 0 && "hH".Contains(InitialConsonant[0].ToString()))
					{
						bool Up = "uU".Contains(sVowel(0)) && "oO".IndexOf(Vowel[1]) < 0 && newChar == sVowel(1);
						FinalConsonant += newChar == sVowel(1) && !Up ? LastChar.ToString() : "";
						Vowel = VNStatic.UNI[VNStatic.UNI.IndexOf(sVowel(0)) + (Up ? 6 : 0) - SubtracIndex(Vowel[0]) - VNStatic.GetSignIndex(pindex)] + VNStatic.UNI[index + (newChar == sVowel(1) && !Up ? 0: 12) - SubtracIndex(Vowel[1])+ VNStatic.GetSignIndex(pindex)] + (Vowel.Length > 2 ? Vowel.Substring(2) : "");
						changed = true;
					}
					else 
					{
						FinalConsonant += newChar == sVowel(TMI) ? LastChar.ToString() : "";
						Vowel = VNStatic.UNI[VNStatic.UNI.IndexOf(sVowel(0)) + (newChar == sVowel(1) ? 0 : 6) - SubtracIndex(Vowel[0]) - VNStatic.GetSignIndex(pindex)] + VNStatic.UNI[index + (newChar == sVowel(1) ? 0: 12) - SubtracIndex(Vowel[1]) + VNStatic.GetSignIndex(pindex)] + (Vowel.Length > 2 ? Vowel.Substring(2) : "");
						changed = true;							
					}
				}
            	if(!changed)
            	{
	            	FinalConsonant += newChar == sVowel(TMI) ? LastChar.ToString(): "" ;
	            	ChangeChar(TMI, newChar == sVowel(TMI) ? removeChar[0] : newChar[0]);
            	}
            	return true;
            }
	#endregion
	#region Xử lý trường hợp đang có chữ ư đánh thêm chữ o (ưo -> ươ)
            if ("oO".Contains(LastChar.ToString()) && VNStatic.uw.Contains(Vowel))
			{ 
            	int Cindex = VNStatic.UNI.IndexOf(LastChar.ToString());
				Vowel = VNStatic.UNI[index - VNStatic.GetSignIndex(index)] + VNStatic.UNI[Cindex + 12 + VNStatic.GetSignIndex(index)];
				return true;
			}
	#endregion
#endregion
		    return false;
		}	
		private int SubtracIndex(char sChar)
		{
			int index = VNStatic.UNI.IndexOf(char.ToLower(sChar).ToString());
			string cstr = VNStatic.UNI[index - VNStatic.GetSignIndex(index)];
			if("ă,ê,ô,ư".Contains(cstr)) return 6;
			if("â,ơ".Contains(cstr)) return 12;
			//if("a,e,o,u".Contains(cstr)) 
			return 0;
		}
	}
}
